package com.xing.game.netty.server;


import com.xing.game.netty.WorkerFactory;
import com.xing.game.netty.Worker;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.SocketChannelConfig;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;

import java.io.IOException;
import java.util.Arrays;

public class NetServerHandler extends LengthFieldBasedFrameDecoder implements ChannelDownstreamHandler {
	private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory
			.getLogger(NetServerHandler.class);
	private ChannelGroup group;
	private Worker worker;
	private Channel channel;
	//private boolean isFirstMsg;
	private WorkerFactory factory;
	
	public NetServerHandler(ChannelGroup group, WorkerFactory factory) {
		//消息号占俩字节，长度属性占俩字节，不调节
		super(5000, 2, 2, 0, 0);
		//isFirstMsg = true;
		if (group == null) {
			throw new NullPointerException("group is null");
		}
		if (factory == null) {
			throw new NullPointerException("factory is null");
		}
		this.group = group;
		this.factory = factory;
	}
	
	@Override
	public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
		channel = e.getChannel();
		((SocketChannelConfig)this.channel.getConfig()).setPerformancePreferences(0, 1, 2);
		super.channelOpen(ctx, e);
	}
	
	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
		group.add(this.channel);
		worker = factory.newWorker(channel);
		logger.debug("收到连接："+channel.getRemoteAddress());
		super.channelConnected(ctx, e);
	}
	
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
//		if(isFirstMsg) {
//			isFirstMsg = false;
//			if(e.getMessage() instanceof ChannelBuffer) {
//				ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
//				if(buffer.readableBytes() > 100) {
//					((ChannelBuffer)e.getMessage()).skipBytes(100);
//				}
//			}
//		}
		super.messageReceived(ctx, e);
	}
	
	@Override
	protected ChannelBuffer extractFrame(ChannelBuffer buffer, int index, int length) {
		try {
			worker.onMessage(buffer);
		} catch (Throwable e) {
			logger.debug("",e);
		}
		return null;
	}

	@Override
	public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
		worker.onDisconnected();
		super.channelDisconnected(ctx, e);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
		if(!(e.getCause() instanceof IOException)) {
			e.getCause().printStackTrace();
		}
	}

	@Override
	public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
		if(logger.isDebugEnabled()){
			if(e instanceof MessageEvent) {
				ChannelBuffer buffer = (ChannelBuffer) ((MessageEvent) e).getMessage();
				logger.debug("send msgId: {}, content: {}", buffer.getUnsignedShort(2), Arrays.toString(buffer.slice(0, buffer.writerIndex()).array()));
			}
		}
		ctx.sendDownstream(e);
	}
}
